/*
 *  Arrow
 *
 *  Created by David Giovannini on 1/5/07.
 *  Copyright 2007 Software by Jove. All rights reserved.
 *
 */
 
#ifndef SBJ_Arrow_Subscription_h
#define SBJ_Arrow_Subscription_h

#include "SBJ/Arrow/Topic.h"
#include "SBJ/Arrow/IDispatcher.h"
#include "SBJ/Interfaces/IRemora.h"

#include "boost/scoped_ptr.hpp"

namespace SBJ
{

namespace Arrow
{

class Subscription : public IRemora
{
public:
	Subscription( void )
	: m_dispatcher( 0 )
	, m_subscriber( 0 )
	, m_activated( false )
	{
	}

	Subscription( IDispatcher& dispatcher, void* subscriber, 
					const Topic& topic, const std::string& filter = std::string() )
	: m_dispatcher( &dispatcher )
	, m_subscriber( subscriber )
	, m_topic( topic )
	, m_filter( filter )
	, m_activated( false )
	{
	}

	Subscription( const Subscription& rhs )
	: m_dispatcher( rhs.m_dispatcher )
	, m_subscriber( rhs.m_subscriber )
	, m_topic( rhs.m_topic )
	, m_filter( rhs.m_filter )
	, m_activated( false )
	{
		if ( rhs.m_activated == true ) throw 0;
	}

	Subscription( const Subscription& rhs, void* subscriber )
	: m_dispatcher( rhs.m_dispatcher )
	, m_subscriber( subscriber )
	, m_topic( rhs.m_topic )
	, m_filter( rhs.m_filter )
	, m_activated( false )
	{
	}
	
	virtual ~Subscription( void )
	{
		deactivate();
	}

	void* getSubscriber( void ) const
	{
		return m_subscriber;
	}
	
	const Topic& getTopic( void ) const
	{
		return m_topic;
	}
	
	const std::string& getFilter( void ) const
	{
		return m_filter;
	}

	bool isLike( const Subscription& rhs )
	{
		return (	m_dispatcher == rhs.m_dispatcher &&
					m_subscriber == rhs.m_subscriber &&
					m_topic == rhs.m_topic );
	}

	Subscription& operator = ( const Subscription& rhs )
	{
		if ( m_activated )
		{
			m_dispatcher->unsubscribe(*this );
			m_activated = false;
		}

		m_dispatcher = rhs.m_dispatcher;
		m_subscriber = rhs.m_subscriber;
		m_topic = rhs.m_topic;
		m_filter = rhs.m_filter;
		return *this;
	}

	bool activate( void )
	{
		if ( m_dispatcher != 0 && m_activated == false )
		{
			m_activated = true;
			return m_dispatcher->subscribe( *this );
		}
		return false;
	}

	bool deactivate( void )
	{
		if ( m_activated )
		{
			m_activated = false;
			return m_dispatcher->unsubscribe(*this );
		}
		return false;
	}

private:
	IDispatcher* m_dispatcher;
	void* m_subscriber;
	Topic m_topic;
	std::string m_filter;
	bool m_activated;
};

}

}

#endif
